<script>
import { defineComponent } from 'vue'
import { mapActions, mapState } from 'vuex'
import conversationService from '@/service/conversationService'

export default defineComponent({
  name: 'ConversationFilterList',
  data() {
    return {
      searchStatus: 'ready', // ready, searching, end
      conversations: [],
      deleteConversationChecker: {
        id: null,
      },
      editConversation: {
        title: null,
        id: null,
        updating: false,
      },
    }
  },
  computed: {
    ...mapState({
      filter: state => state.filter,
    }),
    matches() {
      // 合计conversations中的所有matchResults
      return this.conversations.reduce((acc, cur) => acc + cur.matchResults, 0)
    },
  },
  watch: {
    'filter.search': {
      handler(search) {
        this.searchStatus = 'searching'
        conversationService.getListByFilter({ search }).then(conversations => {
          this.conversations = conversations
          this.searchStatus = 'end'
        })
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    ...mapActions({
      setFilter: 'filter/setFilter',
      setFilterScroll: 'filter/setFilterScroll',
    }),
    toConversation(id) {
      // 存入到searchFloating中
      chrome.storage.local.set({
        searchFloating: {
          conversationId: id,
          filter: {
            search: this.filter.search,
          },
        },
      }).then(() => {
        // 当前chrome tab跳转到会话
        chrome.tabs.update({
          url: `https://chat.openai.com/c/${id}`,
        })
      })
    },

    /**
     * 修改会话标题
     */
    updateConversationTitle() {
      if (this.editConversation.title === ''
        || this.editConversation.title === null
        || this.editConversation.updating
      ) {
        this.editConversation = {
          title: null,
          id: null,
          updating: false,
        }

        return
      }
      this.editConversation.updating = true

      conversationService.updateTitle(this.editConversation.id, this.editConversation.title)
        .then(() => {
          // 找到对应的会话，修改title
          const conversation = this.conversations.find(c => c.id === this.editConversation.id)
          if (conversation) {
            conversation.title = this.editConversation.title
          }
        })
        .catch(err => {
          this.$store.dispatch('alert', err.message)
        }).finally(() => {
          this.editConversation = {
            title: null,
            id: null,
            updating: false,
          }
        })
    },

    /**
     * 删除会话
     */
    removeConversation(id) {
      conversationService.remove(id)
        .then(() => {
          // 从conversations中删除
          const index = this.conversations.findIndex(c => c.id === id)
          if (index !== -1) {
            this.conversations.splice(index, 1)
          }
        })
        .catch(err => {
          this.$store.dispatch('alert', err.message)
        }).finally(() => {
          this.deleteConversationChecker.id = null
        })
    },
    highlight(text) {
      const search = this.filter?.search.trim()
      const parts = text.split(new RegExp(`(${search})`, 'gi'))

      return parts.map(part => ({
        text: part,
        match: part.toLowerCase() === search.toLowerCase(),
      }))
    },
    onScroll() {
      // 在滚动事件发生时更新 filter.scroll
      // 拷贝scrollTop
      const { scrollTop } = this.$refs.filterListWrapper
      this.setFilterScroll(scrollTop)
      chrome.storage.local.set({ filter: this.filter })
    },
  },
  mounted() {
    setTimeout(() => {
      this.$refs.filterListWrapper.scrollTop = this.filter.scroll || 0
    }, 200)
  },
})
</script>

<template>
  <div
    v-cloak
    ref="filterListWrapper"
    id="filterListWrapper"
    @scroll="onScroll"
  >
    <v-sheet
      v-if="searchStatus === 'end' && !conversations?.length"
      width="100%"
      class="pa-4 text-center mx-auto"
    >
      <p class="mb-4 text-medium-emphasis text-body-2">
        Oops, no matching! 😅
      </p>
    </v-sheet>
    <v-list
      v-else-if="searchStatus === 'end'"
      :lines="false"
      density="compact"
      :nav="true"
    >
      <v-list-subheader>
        {{ matches }} matches in {{ conversations.length }} conversations
      </v-list-subheader>
      <div
        v-for="conversation in conversations"
        :key="conversation.id"
      >
        <v-hover
          v-if="editConversation.id !== conversation.id && deleteConversationChecker.id !== conversation.id"
        >
          <template
            v-slot="{ isHovering, props: hoverProps }"
          >
            <v-list-item
              :value="conversation.id"
              :active="false"
              v-bind="hoverProps"
              prepend-icon="mdi-message-outline"
              @click.stop="toConversation(conversation.id)"
            >
              <v-list-item-title>
                <span
                  v-for="(part, idx) in highlight(conversation.title)"
                  :key="idx"
                  :class="part.match ? 'bg-teal-lighten-2 elevation-4 rounded-sm' : ''">
                        {{ part.text }}
                  </span>
              </v-list-item-title>
              <template v-slot:append>
                <v-btn
                  v-show="isHovering"
                  title="rename"
                  icon="mdi-rename-outline"
                  size="x-small"
                  color="grey-darken-1"
                  variant="plain"
                  @click.stop="this.editConversation.id = conversation.id; this.editConversation.title = conversation.title"
                />
                <v-btn
                  v-show="isHovering"
                  title="delete"
                  icon="mdi-delete-outline"
                  size="x-small"
                  color="grey-darken-1"
                  variant="plain"
                  @click.stop="deleteConversationChecker.id = conversation.id"
                />

                <v-chip
                  class="ma-2"
                  size="x-small"
                  color="teal"
                >
                  {{ conversation.matchResults }} results
                </v-chip>
              </template>

            </v-list-item>
          </template>
        </v-hover>
        <v-list-item
          :active="false"
          prepend-icon="mdi-message-outline"
          class="drag-disabled"
          v-else-if="editConversation.id === conversation.id"
        >
          <v-text-field
            v-model="editConversation.title"
            :autofocus="true"
            base-color="teal-lighten-2"
            color="teal-lighten-1"
            variant="outlined"
            density="compact"
            @blur.stop="updateConversationTitle"
            @keyup.enter.stop="updateConversationTitle"
            single-line
            hide-details
          ></v-text-field>
        </v-list-item>
        <v-list-item
          :active="false"
          prepend-icon="mdi-delete"
          class="drag-disabled"
          v-else-if="deleteConversationChecker.id === conversation.id"
        >
          <v-list-item-title>
            Delete "{{ conversation.title }}"?
          </v-list-item-title>
          <template v-slot:append>
            <v-btn
              title="yes"
              icon="mdi-check"
              size="x-small"
              color="grey-darken-1"
              variant="text"
              @click.stop="removeConversation(conversation.id)"
            />
            <v-btn
              title="no"
              icon="mdi-close"
              size="x-small"
              color="grey-darken-1"
              variant="text"
              @click.stop="deleteConversationChecker.id = null"
            />
          </template>
        </v-list-item>
      </div>
    </v-list>
  </div>
</template>

<style lang="scss" scoped>
#filterListWrapper {
  height: 600px - 64 - 16 * 2 - 34;
  overflow-y: auto;
}

::v-deep.v-text-field {
  $max-height: 28px !important;
  max-height: $max-height;

  input {
    max-height: $max-height;
    min-height: $max-height;
    padding-left: 8px;
  }
}
</style>
